package com.nc.mem.tests.custom.map;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import org.testng.Assert;

import com.nc.mem.serial.graph.cust.KeyOnlyPayload;
import com.nc.mem.serial.graph.cust.NotNullNonPolymorphic;
import com.nc.mem.serial.graph.cust.Serializable;
import com.nc.mem.serial.graph.cust.ValOnlyPayload;

@Serializable(include = "*")
public class B {

	static class C0 implements Comparator<String> {

		@Override
		public int compare(final String left, final String right) {
			return right.compareTo(left);
		}
	}

	class C1 implements Comparator<String> {

		@Override
		public int compare(final String left, final String right) {
			return right.compareTo(left);
		}
	}

	static Comparator<String> C2 = new Comparator<String>() {

		@Override
		public int compare(final String left, final String right) {
			return left.compareTo(right);
		}
	};

	Comparator<String> C3 = new Comparator<String>() {

		@Override
		public int compare(final String left, final String right) {
			return left.compareTo(right);
		}
	};

	@NotNullNonPolymorphic
	Map<String, A> cacheA = new HashMap<String, A>();

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheB = new HashMap<String, A>();

	@NotNullNonPolymorphic
	@ValOnlyPayload
	Map<String, A> cacheC = new HashMap<String, A>();

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	Map<String, A> cacheD = new HashMap<String, A>();

	@NotNullNonPolymorphic
	private Map<String, A> cacheE = new HashMap<String, A>();

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	private Map<String, A> cacheF = new HashMap<String, A>();

	@NotNullNonPolymorphic
	@ValOnlyPayload
	private Map<String, A> cacheG = new HashMap<String, A>();

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	private Map<String, A> cacheH = new HashMap<String, A>();

	@NotNullNonPolymorphic
	Map<String, A> cacheI = new TreeMap<String, A>();

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheJ = new TreeMap<String, A>();

	@NotNullNonPolymorphic
	@ValOnlyPayload
	private Map<String, A> cacheK = new TreeMap<String, A>();

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	private Map<String, A> cacheL = new TreeMap<String, A>();

	@NotNullNonPolymorphic
	Map<String, A> cacheM = new TreeMap<String, A>(new C0());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheN = new TreeMap<String, A>(new C1());

	@NotNullNonPolymorphic
	@ValOnlyPayload
	private Map<String, A> cacheO = new TreeMap<String, A>(C2);

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	private Map<String, A> cacheP = new TreeMap<String, A>(C3);

	public void assertAllCachesSized(final int i) {
		for (final Map<?, ?> m : getAllCaches()) {
			Assert.assertEquals(i, m.size());
		}
	}

	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		final B other = (B) obj;
		if (cacheA == null) {
			if (other.cacheA != null) {
				return false;
			}
		} else if (!cacheA.equals(other.cacheA)) {
			return false;
		}
		if (cacheB == null) {
			if (other.cacheB != null) {
				return false;
			}
		} else if (!cacheB.equals(other.cacheB)) {
			return false;
		}
		if (cacheC == null) {
			if (other.cacheC != null) {
				return false;
			}
		} else if (!cacheC.equals(other.cacheC)) {
			return false;
		}
		if (cacheD == null) {
			if (other.cacheD != null) {
				return false;
			}
		} else if (!cacheD.equals(other.cacheD)) {
			return false;
		}
		if (cacheE == null) {
			if (other.cacheE != null) {
				return false;
			}
		} else if (!cacheE.equals(other.cacheE)) {
			return false;
		}
		if (cacheF == null) {
			if (other.cacheF != null) {
				return false;
			}
		} else if (!cacheF.equals(other.cacheF)) {
			return false;
		}
		if (cacheG == null) {
			if (other.cacheG != null) {
				return false;
			}
		} else if (!cacheG.equals(other.cacheG)) {
			return false;
		}
		if (cacheH == null) {
			if (other.cacheH != null) {
				return false;
			}
		} else if (!cacheH.equals(other.cacheH)) {
			return false;
		}
		if (cacheI == null) {
			if (other.cacheI != null) {
				return false;
			}
		} else if (!cacheI.equals(other.cacheI)) {
			return false;
		}
		if (cacheJ == null) {
			if (other.cacheJ != null) {
				return false;
			}
		} else if (!cacheJ.equals(other.cacheJ)) {
			return false;
		}
		if (cacheK == null) {
			if (other.cacheK != null) {
				return false;
			}
		} else if (!cacheK.equals(other.cacheK)) {
			return false;
		}
		if (cacheL == null) {
			if (other.cacheL != null) {
				return false;
			}
		} else if (!cacheL.equals(other.cacheL)) {
			return false;
		}
		if (cacheM == null) {
			if (other.cacheM != null) {
				return false;
			}
		} else if (!cacheM.equals(other.cacheM)) {
			return false;
		}
		if (cacheN == null) {
			if (other.cacheN != null) {
				return false;
			}
		} else if (!cacheN.equals(other.cacheN)) {
			return false;
		}
		if (cacheO == null) {
			if (other.cacheO != null) {
				return false;
			}
		} else if (!cacheO.equals(other.cacheO)) {
			return false;
		}
		if (cacheP == null) {
			if (other.cacheP != null) {
				return false;
			}
		} else if (!cacheP.equals(other.cacheP)) {
			return false;
		}
		return true;
	}

	@SuppressWarnings("unchecked")
	public void fill(final Iterable<A> itr) {
		final Map<?, ?>[] caches = getAllCaches();
		for (final A a : itr) {
			for (@SuppressWarnings("rawtypes")
			final Map map : caches) {
				map.put(a.id, a);
				map.put(a.id + "clone", a.clone());
			}
		}
	}

	private Map<?, ?>[] getAllCaches() {
		return new Map<?, ?>[]{ //
		cacheA, cacheB, cacheC, cacheD, cacheE, cacheF, cacheG, cacheH, //
				cacheI, cacheJ, cacheK, cacheL, cacheM, cacheN, cacheO, cacheP };

	}

	public Map<String, A> getCacheA() {
		return cacheA;
	}

	public Map<String, A> getCacheB() {
		return cacheB;
	}

	public Map<String, A> getCacheC() {
		return cacheC;
	}

	public Map<String, A> getCacheD() {
		return cacheD;
	}

	public Map<String, A> getCacheE() {
		return cacheE;
	}

	public Map<String, A> getCacheF() {
		return cacheF;
	}

	public Map<String, A> getCacheG() {
		return cacheG;
	}

	public Map<String, A> getCacheH() {
		return cacheH;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (cacheA == null ? 0 : cacheA.hashCode());
		result = prime * result + (cacheB == null ? 0 : cacheB.hashCode());
		result = prime * result + (cacheC == null ? 0 : cacheC.hashCode());
		result = prime * result + (cacheD == null ? 0 : cacheD.hashCode());
		result = prime * result + (cacheE == null ? 0 : cacheE.hashCode());
		result = prime * result + (cacheF == null ? 0 : cacheF.hashCode());
		result = prime * result + (cacheG == null ? 0 : cacheG.hashCode());
		result = prime * result + (cacheH == null ? 0 : cacheH.hashCode());
		result = prime * result + (cacheI == null ? 0 : cacheI.hashCode());
		result = prime * result + (cacheJ == null ? 0 : cacheJ.hashCode());
		result = prime * result + (cacheK == null ? 0 : cacheK.hashCode());
		result = prime * result + (cacheL == null ? 0 : cacheL.hashCode());
		result = prime * result + (cacheM == null ? 0 : cacheM.hashCode());
		result = prime * result + (cacheN == null ? 0 : cacheN.hashCode());
		result = prime * result + (cacheO == null ? 0 : cacheO.hashCode());
		result = prime * result + (cacheP == null ? 0 : cacheP.hashCode());
		return result;
	}

	public void setCacheA(final Map<String, A> cacheA) {
		this.cacheA = cacheA;
	}

	public void setCacheB(final Map<String, A> cacheB) {
		this.cacheB = cacheB;
	}

	public void setCacheC(final Map<String, A> cacheC) {
		this.cacheC = cacheC;
	}

	public void setCacheD(final Map<String, A> cacheD) {
		this.cacheD = cacheD;
	}

	public void setCacheE(final Map<String, A> cacheE) {
		this.cacheE = cacheE;
	}

	public void setCacheF(final Map<String, A> cacheF) {
		this.cacheF = cacheF;
	}

	public void setCacheG(final Map<String, A> cacheG) {
		this.cacheG = cacheG;
	}

	public void setCacheH(final Map<String, A> cacheH) {
		this.cacheH = cacheH;
	}

}
